#ifndef  __GPIO_H__
#define  __GPIO_H__

#include "typedef.h"

enum {
    CH0_UT0_TX,
    CH0_UT1_TX,
    CH0_T0_PWM_OUT,
    CH0_T1_PWM_OUT,
    CH0_RTOSH_CLK,
    CH0_BTOSC_CLK,
    CH0_PLL_12M,
    CH0_UT2_TX,
    CH0_CH0_PWM_H,
    CH0_CH0_PWM_L,
    CH0_CH1_PWM_H,
    CH0_CH1_PWM_L,
    CH0_CH2_PWM_H,
    CH0_CH2_PWM_L,
    CH0_WLC_BT_FREQ,
    CH0_T3_PWM_OUT,

    CH1_UT0_TX = 0x10,
    CH1_UT1_TX,
    CH1_T0_PWM_OUT,
    CH1_WLC_BT_PRO,
    CH1_RTOSL_CLK,
    CH1_BTOSC_CLK,
    CH1_SPDIF_DO,
    CH1_UT2_TX,
    CH1_CH0_PWM_H,
    CH1_CH0_PWM_L,
    CH1_CH1_PWM_H,
    CH1_CH1_PWM_L,
    CH1_CH2_PWM_H,
    CH1_CH2_PWM_L,
    CH1_T2_PWM_OUT,
    CH1_T3_PWM_OUT,

    CH2_UT1_RTS = 0x20,
    CH2_UT1_TX,
    CH2_WLC_BT_ACTIVE,
    CH2_T1_PWM_OUT,
    CH2_PLNK_SCLK,
    CH2_BTOSC_CLK,
    CH2_PLL_24M,
    CH2_UT2_TX,
    CH2_CH0_PWM_H,
    CH2_CH0_PWM_L,
    CH2_CH1_PWM_H,
    CH2_CH1_PWM_L,
    CH2_CH2_PWM_H,
    CH2_CH2_PWM_L,
    CH2_T2_PWM_OUT,
    CH2_T3_PWM_OUT,
};

#define IO_GROUP_NUM 		16


#define IO_PORTA_00 				(IO_GROUP_NUM * 0 + 0)
#define IO_PORTA_01 				(IO_GROUP_NUM * 0 + 1)
#define IO_PORTA_02 				(IO_GROUP_NUM * 0 + 2)
#define IO_PORTA_03 				(IO_GROUP_NUM * 0 + 3)
#define IO_PORTA_04 				(IO_GROUP_NUM * 0 + 4)
#define IO_PORTA_05 				(IO_GROUP_NUM * 0 + 5)
#define IO_PORTA_06 				(IO_GROUP_NUM * 0 + 6)
#define IO_PORTA_07 				(IO_GROUP_NUM * 0 + 7)
#define IO_PORTA_08 				(IO_GROUP_NUM * 0 + 8)
#define IO_PORTA_09 				(IO_GROUP_NUM * 0 + 9)
#define IO_PORTA_10 				(IO_GROUP_NUM * 0 + 10)
#define IO_PORTA_11 				(IO_GROUP_NUM * 0 + 11)
#define IO_PORTA_12 				(IO_GROUP_NUM * 0 + 12)
#define IO_PORTA_13 				(IO_GROUP_NUM * 0 + 13)
#define IO_PORTA_14 				(IO_GROUP_NUM * 0 + 14)
#define IO_PORTA_15 				(IO_GROUP_NUM * 0 + 15)

#define IO_PORTB_00 				(IO_GROUP_NUM * 1 + 0)
#define IO_PORTB_01 				(IO_GROUP_NUM * 1 + 1)
#define IO_PORTB_02 				(IO_GROUP_NUM * 1 + 2)
#define IO_PORTB_03 				(IO_GROUP_NUM * 1 + 3)
#define IO_PORTB_04 				(IO_GROUP_NUM * 1 + 4)
#define IO_PORTB_05 				(IO_GROUP_NUM * 1 + 5)
#define IO_PORTB_06 				(IO_GROUP_NUM * 1 + 6)
#define IO_PORTB_07 				(IO_GROUP_NUM * 1 + 7)
#define IO_PORTB_08 				(IO_GROUP_NUM * 1 + 8)
#define IO_PORTB_09 				(IO_GROUP_NUM * 1 + 9)
#define IO_PORTB_10 				(IO_GROUP_NUM * 1 + 10)
#define IO_PORTB_11 				(IO_GROUP_NUM * 1 + 11)

#define IO_PORTC_00 				(IO_GROUP_NUM * 2 + 0)
#define IO_PORTC_01 				(IO_GROUP_NUM * 2 + 1)
#define IO_PORTC_02 				(IO_GROUP_NUM * 2 + 2)
#define IO_PORTC_03 				(IO_GROUP_NUM * 2 + 3)
#define IO_PORTC_04 				(IO_GROUP_NUM * 2 + 4)
#define IO_PORTC_05 				(IO_GROUP_NUM * 2 + 5)
#define IO_PORTC_06 				(IO_GROUP_NUM * 2 + 6)
#define IO_PORTC_07 				(IO_GROUP_NUM * 2 + 7)

#define IO_PORTD_00 				(IO_GROUP_NUM * 3 + 0)
#define IO_PORTD_01 				(IO_GROUP_NUM * 3 + 1)
#define IO_PORTD_02 				(IO_GROUP_NUM * 3 + 2)
#define IO_PORTD_03 				(IO_GROUP_NUM * 3 + 3)
#define IO_PORTD_04 				(IO_GROUP_NUM * 3 + 4)
#define IO_PORTD_05 				(IO_GROUP_NUM * 3 + 5)

#define IO_MAX_NUM 					(IO_PORTD_05 + 1)

#define PR_IO_OFFSET                0
#define IO_PORT_R0 				    (IO_MAX_NUM + PR_IO_OFFSET)
#define IO_PORT_R1 				    (IO_MAX_NUM + PR_IO_OFFSET + 1)

#define USB_IO_OFFSET               2
#define IO_PORT_DP                  (IO_MAX_NUM + USB_IO_OFFSET)
#define IO_PORT_DM                  (IO_MAX_NUM + USB_IO_OFFSET + 1)

#define P33_IO_OFFSET               4
#define IO_LDOIN_DET                (IO_MAX_NUM + P33_IO_OFFSET)
#define IO_LVCMP_DET                (IO_MAX_NUM + P33_IO_OFFSET + 1)

#define IO_PORT_MAX					(IO_LVCMP_DET + 1)

#define GPIOA                       (IO_GROUP_NUM * 0)
#define GPIOB                       (IO_GROUP_NUM * 1)
#define GPIOC                       (IO_GROUP_NUM * 2)
#define GPIOD                       (IO_GROUP_NUM * 3)

enum {
    INPUT_CH0,
    INPUT_CH1,
    INPUT_CH2,
    INPUT_CH3,
};

enum gpio_op_mode {
    GPIO_SET = 1,
    GPIO_AND,
    GPIO_OR,
    GPIO_XOR,
};

enum gpio_direction {
    GPIO_OUT = 0,
    GPIO_IN = 1,
};

struct gpio_reg {
    volatile unsigned int out;
    volatile unsigned int in;
    volatile unsigned int dir;
    volatile unsigned int die;
    volatile unsigned int pu;
    volatile unsigned int pd;
    volatile unsigned int hd0;
    volatile unsigned int hd;
    volatile unsigned int dieh;
};


/**
 * @brief usb_iomode, usb引脚设为普通IO
 *
 * @param enable 1，使能；0，关闭
 */
void usb_iomode(u32 enable);

/**
 * @brief gpio2reg，获取引脚序号对应的端口寄存器地址
 *
 * @param gpio 参考宏IO_PORTx_xx，如IO_PORTA_00
 *
 * @return 端口寄存器地址，如JL_PORTA,JL_PORTB,,,
 */
struct gpio_reg *gpio2reg(u32 gpio);

/**
 * @brief gpio_set_direction，设置引脚方向
 *
 * @param gpio 参考宏IO_PORTx_xx，如IO_PORTA_00
 * @param value 1，输入；0，输出
 *
 * @return 0：成功  非0：失败
 */
int gpio_set_direction(u32 gpio, u32 value);

/**
 * @brief gpio_read  &  gpio_read_input_value，读取引脚的输入电平，引脚为输入模式时才有效
 *
 * @param gpio 参考宏IO_PORTx_xx，如IO_PORTA_00
 *
 * @return 电平值
 */
int gpio_read(u32 gpio);
int gpio_read_input_value(u32 gpio);

/**
 * @brief gpio_direction_input，将引脚直接设为输入模式
 *
 * @param gpio 参考宏IO_PORTx_xx，如IO_PORTA_00
 *
 * @return 0：成功  非0：失败
 */
int gpio_direction_input(u32 gpio);

/**
 * @brief gpio_write  &  gpio_set_output_value，设置引脚输出的电平，引脚为输出模式时才有效
 *
 * @param gpio 参考宏IO_PORTx_xx，如IO_PORTA_00
 * @param value 1，输出1,  0，输出0
 *
 * @return 0：成功  非0：失败
 */
int gpio_write(u32 gpio, u32 value);
int gpio_set_output_value(u32 gpio, u32 value);

/**
 * @brief gpio_direction_output，设置引脚的方向为输出，并设置一下电平
 *
 * @param gpio 参考宏IO_PORTx_xx，如IO_PORTA_00
 * @param value 1，输出1；0，输出0
 *
 * @return 0：成功  非0：失败
 */
int gpio_direction_output(u32 gpio, u32 value);

/**
 * @brief gpio_set_pull_up，设置引脚的上拉，上拉电阻10K，当引脚为输入模式时才有效
 *
 * @param gpio 参考宏IO_PORTx_xx，如IO_PORTA_00
 * @param value 1，上拉；0，不上拉
 *
 * @return 0：成功  非0：失败
 */
int gpio_set_pull_up(u32 gpio, u32 value);

/**
 * @brief gpio_set_pull_down，设置引脚的下拉，下拉电阻10K，当引脚为输入模式时才有效
 *
 * @param gpio 参考宏IO_PORTx_xx，如IO_PORTA_00
 * @param value 1，下拉；0，不下拉
 *
 * @return 0：成功  非0：失败
 */
int gpio_set_pull_down(u32 gpio, u32 value);

/**
 * @brief gpio_set_hd0, 设置引脚的内阻，当引脚为输出模式时才有效
 *
 * @param gpio 参考宏IO_PORTx_xx，如IO_PORTA_00
 * @param value 1，关闭内阻增强输出  0，存在内阻，芯片默认的
 *
 * @return 0：成功  非0：失败
 */
int gpio_set_hd0(u32 gpio, u32 value);

/**
 * @brief gpio_set_hd, 设置引脚的输出电流，当引脚为输出模式时才有效
 *
 * @param gpio 参考宏IO_PORTx_xx，如IO_PORTA_00
 * @param value 1，电流变大增强输出； 0，默认电流
 *
 * @return 0：成功  非0：失败
 */
int gpio_set_hd(u32 gpio, u32 value);

/**
 * @brief gpio_set_die，设置引脚为数字功能还是模拟功能，比如引脚作为ADC的模拟输入，则die要置0
 *
 * @param gpio 参考宏IO_PORTx_xx，如IO_PORTA_00
 * @param value 1，数字功能，即01信号；  0，跟电压先关的模拟功能
 *
 * @return 0：成功  非0：失败
 */
int gpio_set_die(u32 gpio, u32 value);

/**
 * @brief gpio_set_dieh, 设置引脚为数字功能还是模拟功能，但模拟功能时，跟die的不一样而已
 *
 * @param gpio 参考宏IO_PORTx_xx，如IO_PORTA_00
 * @param value 1，数字功能，即01信号；  0，跟电压先关的模拟功能
 *
 * @return 0：成功  非0：失败
 */
int gpio_set_dieh(u32 gpio, u32 value);

/**
 * @brief get_gpio, 解析字符串，获取引脚对应的序号
 *
 * @param p 引脚字符串，如“PA00”, "PA01"，，，，
 *
 * @return 引脚对应的序号. 如传入“PB01”，返回17
 */
u32 get_gpio(const char *p);

/**
 * @brief gpio_output_channel, 非硬件IO可以通过outputchannel输出部分外设的信号
 *
 * @param gpio 参考宏IO_PORTx_xx，如IO_PORTA_00, 非串口的硬件rx 引脚，即任意IO
 * @param CHx_xxx，在gpio.h上面的枚举中取值，如CH0_CH0_PWM_H, CH1_UT0_TX, , , ,
 *
 * @return 0：成功  非0：失败
 */
int gpio_output_channel(u32 gpio, u32 CHx_xxx);

/**
 * @brief gpio_uart_rx_input_channle, uart模块通过inputchannel选择非硬件IO做串口的rx
 *
 * @param gpio 参考宏IO_PORTx_xx，如IO_PORTA_00, 非串口的硬件rx 引脚，即任意IO
 * @param uart_idx，串口号 0: uart0  1；uart1  2：uart2
 * @param ch，取值范围0~3，即inputchannel0~3
 *
 * @return 0：成功  非0：失败
 */
int gpio_uart_rx_input_channel(u32 gpio, u32 uart_idx, u32 ch);

/**
 * @brief gpio_set_uartx, uartx模块设置硬件IO做串口的tx/rx
 *
 * @param ch，取值范围0~3，即uartx硬件IO组别0~3
 *
 * @return 0：成功  非0：失败
 */
int gpio_set_uart0(u32 ch);
int gpio_set_uart1(u32 ch);
int gpio_set_uart2(u32 ch);

/**
 * @brief gpio_timer_cap_input_channle, timer模块通过inputchannel选择非硬件IO做timer的输入捕捉
 *
 * @param gpio 参考宏IO_PORTx_xx，如IO_PORTA_00, 非timer的硬件cap 引脚，即任意IO
 * @param timer_idx timer号 0：timer0  1: timer1  2: timer2  3:timer3
 *
 * @return 0：成功  非0：失败
 */
int gpio_timer_cap_input_channel(u32 gpio, u32 timer_idx);

/**
 * @brief gpio_irflt_input_channle, irflt模块通过inputchannel选择非硬件IO做irflt的输入捕捉, 经过irflt的信号再送给timer做捕捉
 *
 * @param gpio 参考宏IO_PORTx_xx，如IO_PORTA_00, 任意IO
 * @param ir_tmr_idx 捕捉irflt信号的timer号 0：timer0  1: timer1  2: timer2  3:timer3
 *
 * @return 0：成功  非0：失败
 */
int gpio_irflt_input_channel(u32 gpio, u32 ir_tmr_idx);



#endif  /*GPIO_H*/

